﻿using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Xml.Linq;
using System.Xml.Serialization;

namespace Nardax.ServiceModel.Discovery.Bindings
{
    public static class BindingSerializer
    {
        public const string RootElementName = "Binding";
        public const string TypeAttributeName = "T";

        public static XElement Serialize(Binding binding)
        {
            var netTcpBinding = binding as NetTcpBinding;
            if (netTcpBinding != null)
            {
                var serializableBinding = new SerializableNetTcpBinding(netTcpBinding);
                var serializer = new XmlSerializer(typeof(SerializableNetTcpBinding));
                return serializer.SerializeAsXElement(serializableBinding);
            }

            var wsHttpBinding = binding as WSHttpBinding;
            if (wsHttpBinding != null)
            {
                var serializableBinding = new SerializableWSHttpBinding(wsHttpBinding);
                var serializer = new XmlSerializer(typeof(SerializableWSHttpBinding));
                return serializer.SerializeAsXElement(serializableBinding);
            }

            return new XElement(RootElementName);
        }

        public static Binding Deserialize(XElement bindingElement)
        {
            var typeAttribute = bindingElement.Attribute(TypeAttributeName);
            if (typeAttribute != null)
            {
                XmlSerializer serializer = null;

                switch (typeAttribute.Value)
                {
                    case "System.ServiceModel.NetTcpBinding":
                        serializer = new XmlSerializer(typeof(SerializableNetTcpBinding));
                        var sntb = (SerializableNetTcpBinding)serializer.Deserialize(bindingElement.CreateReader());
                        return sntb.Binding;

                    case "System.ServiceModel.WSHttpBinding":
                        serializer = new XmlSerializer(typeof(SerializableWSHttpBinding));
                        var swhb = (SerializableWSHttpBinding)serializer.Deserialize(bindingElement.CreateReader());
                        return swhb.Binding;
                }
            }

            throw new ArgumentException("Invalid value", "bindingElement");
        }
    }
}
